<?php
/**
 * 数据保存trait
 * User: dxk
 * Date: 2020/07/18
 */

namespace App\Traits;

use App\Library\Service\Verify;

trait ModelStoreTrait
{
    //自动过滤表情符号
    protected bool $auto_filter_emoji = false;
    //自动trim字符串
    protected bool $auto_trim = true;
    //输入参数
    protected int $operate_id = 0;
    //错误信息
    protected string $operate_by = '';

    //操作人
    private array $params = [];
    private array $errors = [];

    /**
     * 设置操作人（必填）
     * @param $operate_id
     * @param $operate_by
     * @return $this
     */
    public function setOperate($operate_id, $operate_by)
    {
        $this->operate_id = (int)$operate_id;
        $this->operate_by = trim($operate_by);
        return $this;
    }

    /**
     * @param $method
     * @param $parameters
     * @return $this
     */
    public function __call($method, $parameters)
    {
        if (count($parameters) != 1) {
            throw new \Exception('不支持的方法');
        }
        $method = \Str::kebab($method);
        $method = explode('-', $method);
        unset($method[0]);
        $method = implode('_', $method);
        if (!empty($method)) {
            $this->setParam($method, $parameters[0]);
        }
        return $this;
    }

    /**
     * 设置参数
     * @param string $key
     * @param $value
     * @param bool $auto_trim 是否自动trim
     * @return $this
     */
    protected function setParam(string $key, $value, ?bool $auto_trim = null): static
    {
        $auto_trim = $auto_trim === null ? $this->auto_trim : $auto_trim;
        if ($auto_trim) {
            if (is_string($value) || is_null($value)) $value = trim($value);
//            if (is_int($value)) {
//                $value = (int)$value;
//            } elseif (is_numeric($value)) {
//                $value = (float)$value;
//                if ($value == (int)$value) {
//                    $value = (int)$value;
//                }
//            }
        }
        if ($this->auto_filter_emoji && $auto_trim) {
            $value = Verify::filterEmoji($value);
        }
        $this->params[$key] = $value;
        return $this;
    }

    /**
     * 检测字段最大长度
     * @param array $fields [[内容，最大长度，错误提示前缀]]
     * @return array
     */
    protected function checkFieldMaxLength(array $fields): array
    {
        $checks = [];
        foreach ($fields as $field) {
            if (mb_strlen($field[0]) > $field[1]) {
                $checks[] = $field[2] . '不能超过' . $field[1] . '个文字';
            }
        }
        return $checks;
    }

    /**
     * 获取参数
     * @param string $key
     * @param mixed $default
     * @return mixed
     */
    protected function getParam(string $key, $default = '')
    {
        if (array_key_exists($key, $this->params)) {
            return $this->params[$key];
        } else {
            return $default;
        }
    }

    /**
     * 检测必须的参数
     * @param array $required_param
     * @return $this
     */
    protected function check_required_param(array $required_param)
    {

        foreach ($required_param as $param) {
            if (!isset($this->params[$param])) {
                $this->setError('参数' . $param . '未传递');
            }
            if ($this->params[$param] === '') {
                $this->setError('参数' . $param . '为空');
            }
        }
        if (empty($this->operate_by)) {
            $this->setError('参数operate_by未传递');
        }
        return $this;
    }

    /**
     * 收集错误信息
     * @param $error
     * @return $this
     */
    protected function setError($error)
    {
        $this->errors[] = $error;
        return $this;
    }

    /**
     * 检测必须的参数
     * @param array $required_param
     * @param array $params
     * @return $this
     */
    protected function check_required_param_all(array $required_param, $params = [])
    {
        $params = empty($params) ? $this->params : $params;
        foreach ($required_param as $key => $param) {
            if (!isset($params[$key])) {
                $this->setError('参数' . $param . '未传递');
            }
            if (is_array($param)) {
                $checkMode = explode('|', $param['check']);
                foreach ($checkMode as $check) {
                    if (method_exists(new Verify(), $check)) {
                        if (!Verify::{$check}($params[$key])) {
                            $this->setError($param['msg']);
                        }
                    }
                }
            }
        }
        if (empty($this->operate_by)) {
            $this->setError('参数operate_by未传递');
        }
        return $this;
    }

    /**
     * 获取变化内容
     * @param array $change_data
     * @return string
     */
    protected function getChangeStr(array $change_data): string
    {
        return easy_get_change_str($change_data);
    }
}
